package jmine.tec.report.domain;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.Transient;

import jmine.tec.utils.AbstractTuple;
import jmine.tec.utils.Tuple;
import jmine.tec.utils.UnmodifiableTuple;
import jmine.tec.utils.io.IOUtils;

/**
 * Uma tupla de String para qualquer coisa que eh persistivel. Usa uma forma serializada para persistir o segundo elemento.
 * 
 * @author takeshi
 */
@Entity
public class PersistableTuple extends AbstractTuple<String, Object> implements Tuple<String, Object>, Comparable<PersistableDataColumn> {

    private Long id;

    private String head;

    private Object tail;

    private int prioridade;

    /**
     */
    public PersistableTuple() {
    }

    /**
     * @param head the head
     * @param tail the tail
     */
    public PersistableTuple(String head, Object tail) {
        super();
        this.head = head;
        this.tail = tail;
    }

    /**
     * @see java.lang.Comparable#compareTo(java.lang.Object)
     * @param o o outro datacolumn
     * @return int
     */
    public int compareTo(final PersistableDataColumn o) {
        if (this.prioridade < o.getPrioridade()) {
            return -1;
        }
        if (this.prioridade > o.getPrioridade()) {
            return 1;
        }
        return 0;
    }

    /**
     * {@inheritDoc}
     */
    public Tuple<String, Object> copy() {
        return new PersistableTuple(this.head, this.tail);
    }

    /**
     * {@inheritDoc}
     */
    public Tuple<Object, String> invert() {
        return new UnmodifiableTuple<Object, String>(this.tail, this.head);
    }

    /**
     * @return the head
     */
    public String getHead() {
        return this.head;
    }

    /**
     * @param head the head to set
     */
    public void setHead(String head) {
        this.head = head;
    }

    /**
     * @return the tail
     */
    @Transient
    public Object getTail() {
        return this.tail;
    }

    /**
     * @param tail the tail to set
     */
    public void setTail(Object tail) {
        this.tail = tail;
    }

    /**
     * @return the id
     */
    @Id
    @GeneratedValue
    public Long getId() {
        return this.id;
    }

    /**
     * @param id the id to set
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * @return byte[]
     */
    @Lob
    protected byte[] getSerializedTail() {
        if (this.tail == null) {
            return new byte[0];
        }
        return IOUtils.serializeObject(this.tail);
    }

    /**
     * @param sTail the tail
     */
    protected void setSerializedTail(byte[] sTail) {
        if (sTail == null || sTail.length == 0) {
            this.tail = null;
        } else {
            try {
                this.tail = IOUtils.deserializeObject(sTail);
            } catch (ClassNotFoundException e) {
                throw new IllegalArgumentException(e);
            }
        }
    }

    /**
     * @return the prioridade
     */
    @Column(name = "PRIORIDADE")
    public int getPrioridade() {
        return this.prioridade;
    }

    /**
     * @param prioridade the prioridade to set
     */
    public void setPrioridade(final int prioridade) {
        this.prioridade = prioridade;
    }
}
